import { AnimationClip, Node, Animation, v3, Widget, Button, EventHandle, EventHandler, UIOpacity, UITransform, Vec3 } from "cc";
import { _decorator, Component, tween } from "cc";
import { LoggerManager } from "../../manger/LoggerManager";
import { BaseComponent } from "./BaseComponent";
import { UIManager } from "../../manger/UIManager";



function DefaltOpenTween(viewNode: Node) {
    return new Promise((resolve, reject) => {
        const duration = 0.3
        viewNode.setScale(new Vec3(0.3, 0.3, 0.3))
        viewNode.getComponent(UIOpacity).opacity = 255
        tween(viewNode).to(duration, { scale: new Vec3(1, 1, 1) }, { easing: 'expoOut' }).call(() => {
            resolve(null)
        }).start()

    })
}

function DefaltCloseTween(viewNode: Node) {
    return new Promise((resolve, reject) => {
        const duration = 0.25
        tween(viewNode).to(duration, { scale: new Vec3(0, 0, 0) }, { easing: 'expoOut' }).call(
            () => {
                resolve(null)
            }
        ).start()
    })

}

export function DrawerOpenTween(viewNode: Node) {
    return new Promise((resolve, reject) => {
        const y = viewNode.getPosition().y
        viewNode.setPosition(viewNode.position.x, y - viewNode.getComponent(UITransform).height)
        viewNode.getComponent(UIOpacity).opacity = 255
        tween(viewNode).to(0.2, { position: new Vec3(viewNode.position.x, y) }, { easing: 'sineOut' }).call(() => {
            resolve(null)
        }).start()
    })
}
export function DrawerCloseTween(viewNode: Node) {
    return new Promise((resolve, reject) => {
        const y = viewNode.getPosition().y - viewNode.getComponent(UITransform).height
        tween(viewNode).to(0.15, { position: new Vec3(viewNode.position.x, y) }, { easing: 'sineOut' }).call(() => {
            resolve(null)
        }).start()
    })
}


const { ccclass, property } = _decorator;
/**界面基类 */
@ccclass('BaseView')
export abstract class BaseView<CustomProp = any> extends BaseComponent<CustomProp> {
    /**打开界面时需要的配置信息 */
    public static get uiViewConfig(): UIViewConfig {
        return (this as any).__uiViewConfig
    }

    getClassName() {
        //@ts-ignore
        return this.name.slice(0, this.name.indexOf("<"))
    }
    // @property(AnimationClip)
    aniOpen: AnimationClip = null;
    // @property(AnimationClip)
    aniClose: AnimationClip = null;


    /**可打开多个本界面 */
    canOpenMultiple = false
    @property({ tooltip: '是否在打开时隐藏之前打开的界面' })
    /**是否在打开时隐藏之前打开的界面 */
    hidePreViews: boolean = false


    /**
     * 关闭回调
     */
    _closeCbks: Function[] = []

    addCloseCbk(cbk: Function) {
        this._closeCbks.push(cbk)
    }
    /**
    * 有默认的黑背景
    */
    @property({ tooltip: '有默认的黑背景' })
    hasBlackBg: boolean = true
    /**
     * 点击黑背景是否自动关闭
     */
    @property({ tooltip: '点击黑背景是否自动关闭', visible(this: BaseView) { return this.hasBlackBg } })
    autoCloseOnTouchBlackBg: boolean = true

    /**
     * 黑背景透明度
     */
    @property({ tooltip: '黑背景透明度', visible(this: BaseView) { return this.hasBlackBg } })
    blackBgOpacity: number = 180

    /**是否禁用出场入场动画 */
    @property({ tooltip: '是否禁用出入场动画' })
    disableAnim: boolean = false

    /**
     * 当界面打开
     */
    abstract onOpen();


    /**当界面关闭 */
    onClose() { }

    /**当界面进入后台（被上层全屏界面完全遮挡） */
    onHide() { }

    /**当界面返回前台 */
    onShow() { }

    /**当界面暂停（被上层界面部分或完全遮挡） */
    onPause() { }

    /**当界面继续 */
    onResume() { }


    /**是否在后台 */
    isHide: boolean = false

    /**是否已暂停 */
    isPaused: boolean = false

    /**黑背景 */
    _blackBg: Node = null

    _closing = false
    /**关闭界面 */
    _close() {
        LoggerManager.instance().log("view onClose", this.constructor.name, this)
        this.onClose()
        this._closeCbks.forEach(i => {
            if (i) {
                i(this)
            }
        })
        this.node.destroy()
    }

    /**
     * 关闭界面,还是通过UIManager关闭，这里只是一个快捷入口
     * @param closeCbk 关闭完成回调
     * @param disableAnim 禁用出场动画
     */
    close(closeCbk?: (view: BaseView) => void, disableAnim?: boolean) {
        UIManager.instance().closeView(
            this,
            {
                closeCbk: closeCbk,
                disableAnim: disableAnim
            }
        )
    }

    /**点击关闭，用来给关闭按钮调用 */
    onTouchClose() {
        this.close()
    }

    /**进入后台 */
    hide() {
        this.node.active = false
        this.isHide = true
        this.onHide()
    }

    /**返回前台 */
    show() {
        this.node.active = true
        this.isHide = false
        this.onShow()
    }

    /**暂停 */
    pause() {
        this.isPaused = true
        this.onPause()
    }

    /**继续 */
    resume() {
        this.isPaused = false
        this.onResume()
    }

    /**显示黑背景 */
    // showBlackBg(show: boolean) {
    //     if (this._blackBg && this._blackBg.parent != this.node) {
    //         this._blackBg.parent = this.node
    //         this._blackBg.setSiblingIndex(0)
    //         if (this.autoCloseOnTouchBlackBg) {
    //             const eventHandler = new EventHandler();
    //             eventHandler.target = this.node;
    //             eventHandler.component = "BaseView";
    //             eventHandler.handler = "onTouchBlockBg";
    //             this._blackBg.getComponent(Button).clickEvents.push(eventHandler)
    //         }
    //     }

    //     if (this._blackBg) {
    //         this._blackBg.active = show
    //     }
    // }

    onTouchBlockBg() {
        if (this.autoCloseOnTouchBlackBg) {
            this.onTouchClose()
        }
    }

    private playAniClip(clip: AnimationClip, cbk: Function) {
        let animationComp = this.node.getComponent(Animation)
        if (!animationComp) {
            this.node.addComponent(Animation)
            animationComp = this.node.getComponent(Animation)
        }

        if (
            animationComp.clips.findIndex((aniClip) => {
                return aniClip.name == clip.name
            })
            ==
            -1) {
            animationComp.addClip(clip)
        }
        animationComp.play(clip.name)
        if (cbk) {
            tween(this.node).delay(clip.duration).call(cbk.bind(this)).start();
        }
    }

    tweenOpen = DefaltOpenTween
    tweenClose = DefaltCloseTween

    /**播放打开动画 */
    playOpenAnim(cbk?: Function) {
        if (this.aniOpen) {
            this.playAniClip(this.aniOpen, cbk)
            this.aniOpen.wrapMode = AnimationClip.WrapMode.Loop
        } else {
            // this.node.getComponentsInChildren(Widget).forEach(i => { i.updateAlignment(); i.enabled = false })
            this.node.getComponent(UIOpacity).opacity = 0
            /**需要延迟一帧，不然widet会影响缩放 */
            this.scheduleOnce(() => {
                this.tweenOpen(this.node).then(() => {
                    cbk && cbk();
                })

            })

        }
    }

    /**播放关闭动画 */
    playCloseAnim(cbk?: Function) {
        if (this.aniClose) {
            this.playAniClip(this.aniClose, cbk)
        } else {
            this.tweenClose(this.node).then(() => {
                cbk && cbk();
            })
        }
    }
}


/**打开界面时需要的配置信息 */
export interface UIViewConfig {
    /**视图id ,暂时没用到*/
    viewId?: number;
    /** 资源包名 */
    bundle?: string;
    /** 预制资源相对路径 */
    prefabPath: string;
}


/**
 * 设置视图配置的类型装饰器
 * @param uiViewConfig 配置对象,填入viewId的视图会自动注册到uiManager
 * @returns 
 */
export function regView(uiViewConfig: UIViewConfig): ClassDecorator {
    //@ts-ignore
    if (!regView.clzArr) {
        //@ts-ignore
        regView.clzArr = []
    }
    return function (target) {
        //@ts-ignore
        regView.clzArr.push(target)
        Object.defineProperty(
            target,
            '__uiViewConfig',
            {
                value: uiViewConfig,
                writable: false,
                enumerable: false
            }
        )
        UIManager.instance().registerView(target as any)


    }
}